#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
PostgreSQL监控仪表板模块
提供实时命令行方式的数据库监控功能
"""

import os
import time
import psycopg2
import threading
import datetime
import platform
import signal
import sys
from typing import Dict, List, Tuple, Optional, Any, Union
from dataclasses import dataclass

from rich.live import Live
from rich.layout import Layout
from rich.panel import Panel
from rich.table import Table
from rich.console import Console
from rich.text import Text
from rich.progress_bar import ProgressBar
from rich.box import ROUNDED

from ..core import config
from ..core.ui_utils import console, STYLES, SYMBOLS, print_info, print_error, print_warning, print_success, get_input
from ..core.utils import logger

class PostgresqlMonitor:
    """PostgreSQL数据库监控类"""
    
    def __init__(self, refresh_interval: int = 5):
        """
        初始化PostgreSQL监控器
        
        Args:
            refresh_interval: 刷新间隔（秒）
        """
        self.refresh_interval = refresh_interval
        self.running = False
        self.conn = None
        self.layout = None
        self.version_info = None
        self.uptime_start = None
        self._stop_event = threading.Event()
        self._live_display = None  # 添加对Live对象的引用
        
    def connect(self, host: str = "localhost", port: int = 5432, 
                dbname: str = "postgres", user: str = "postgres", 
                password: Optional[str] = None) -> bool:
        """连接到PostgreSQL数据库"""
        try:
            # 保存连接参数用于可能的重连
            self._connection_params = {
                'host': host,
                'port': port,
                'dbname': dbname,
                'user': user,
                'password': password
            }
            
            self.conn = psycopg2.connect(
                host=host,
                port=port,
                dbname=dbname,
                user=user,
                password=password
            )
            self.conn.set_session(autocommit=True)
            
            # 获取PostgreSQL版本信息
            with self.conn.cursor() as cursor:
                cursor.execute("SELECT version()")
                self.version_info = cursor.fetchone()[0]
                
                # 获取服务启动时间
                cursor.execute("SELECT pg_postmaster_start_time()")
                self.uptime_start = cursor.fetchone()[0]
                
                # 检查是否为主库或从库
                try:
                    cursor.execute("SELECT pg_is_in_recovery()")
                    self.is_replica = cursor.fetchone()[0]
                except Exception:
                    self.is_replica = False
                
            return True
        except Exception as e:
            print_error(f"连接数据库失败: {e}")
            return False

    def _execute_query(self, query: str) -> List[tuple]:
        """执行SQL查询并返回结果"""
        try:
            if not self.conn or self.conn.closed:
                print_warning("数据库连接已关闭，正在尝试重连...")
                if not hasattr(self, '_connection_params'):
                    # 如果没有保存连接参数，无法重连
                    logger.error("无法重新连接数据库：没有保存的连接参数")
                    return []
                
                # 尝试使用保存的连接参数重连
                if not self.connect(**self._connection_params):
                    return []
                
            with self.conn.cursor() as cursor:
                cursor.execute(query)
                return cursor.fetchall()
        except Exception as e:
            logger.error(f"执行查询时出错: {e}")
            return []

    def stop(self):
        """停止监控"""
        self._stop_event.set()
        self.running = False
        # 确保关闭Live显示
        if self._live_display is not None:
            try:
                self._live_display.stop()
            except Exception as e:
                logger.error(f"关闭Live显示时出错: {e}")
                
        # 关闭数据库连接
        if self.conn and not self.conn.closed:
            try:
                self.conn.close()
            except Exception as e:
                logger.error(f"关闭数据库连接时出错: {e}")
            
    def _create_layout(self) -> Layout:
        """创建监控仪表板布局"""
        layout = Layout(name="root")
        
        # 分割为上下两部分
        layout.split(
            Layout(name="header", size=3),
            Layout(name="main")
        )
        
        # 主区域分为左右两部分
        layout["main"].split_row(
            Layout(name="left", ratio=1),
            Layout(name="right", ratio=1)
        )
        
        # 左侧区域分为三个面板
        layout["left"].split(
            Layout(name="overview", size=7),
            Layout(name="connections"),
            Layout(name="queries", size=15)
        )
        
        # 右侧区域分为三个面板
        layout["right"].split(
            Layout(name="tablespaces", size=7),
            Layout(name="cache"),
            Layout(name="wal", size=10)
        )
        
        return layout
    
    def start(self):
        """启动监控仪表板"""
        if not self.conn:
            print_warning("未连接到数据库，请先连接")
            host = get_input("请输入数据库主机", "localhost")
            port = int(get_input("请输入数据库端口", "5432"))
            dbname = get_input("请输入数据库名", "postgres")
            user = get_input("请输入用户名", "postgres")
            password = get_input("请输入密码(留空则无密码)")
            
            if not self.connect(host, port, dbname, user, password or None):
                return
        
        try:
            self.running = True
            self._stop_event.clear()
            self.layout = self._create_layout()
            
            # 保存原始信号处理器
            original_sigint_handler = signal.getsignal(signal.SIGINT)
            
            # 自定义信号处理函数
            def signal_handler(sig, frame):
                print_info("\n正在退出监控仪表板...")
                self.stop()
                # 延迟一下再恢复原始处理器，避免冲突
                time.sleep(0.5)
                # 恢复原始信号处理器
                signal.signal(signal.SIGINT, original_sigint_handler)
                
            # 设置新的信号处理器
            signal.signal(signal.SIGINT, signal_handler)
            
            # 使用Rich的Live视图更新仪表板
            with Live(self.layout, refresh_per_second=4, screen=True) as live:
                self._live_display = live  # 保存Live对象的引用
                
                while self.running and not self._stop_event.is_set():
                    try:
                        self._update_dashboard()
                        # 使用事件等待替代sleep，以便更快响应停止信号
                        self._stop_event.wait(self.refresh_interval)
                    except Exception as e:
                        logger.error(f"更新仪表板时出错: {e}")
                        # 如果出现错误，短暂暂停以避免无限循环错误
                        time.sleep(0.5)
                        
            # 确保恢复原始信号处理器
            signal.signal(signal.SIGINT, original_sigint_handler)
                    
        except Exception as e:
            logger.error(f"监控仪表板运行时错误: {e}")
        finally:
            # 确保Live显示被停止
            if hasattr(self, '_live_display') and self._live_display is not None:
                try:
                    self._live_display.stop()
                except Exception:
                    pass
                
            # 确保数据库连接被关闭
            if self.conn and not self.conn.closed:
                try:
                    self.conn.close()
                except Exception:
                    pass
                
            self.running = False
            print_info("监控已停止")
            
    def _update_dashboard(self):
        """更新仪表板内容"""
        if not self.layout:
            return
            
        # 1. 更新标题
        current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.layout["header"].update(
            Panel(
                f"PostgreSQL 监控仪表板 - {current_time} [按 Ctrl+C 退出]",
                style="bold magenta",
                box=ROUNDED
            )
        )
        
        # 2. 更新数据库概览
        self.layout["overview"].update(self._get_overview_panel())
        
        # 3. 更新连接信息
        self.layout["connections"].update(self._get_connections_panel())
        
        # 4. 更新查询性能
        self.layout["queries"].update(self._get_queries_panel())
        
        # 5. 更新表空间使用情况
        self.layout["tablespaces"].update(self._get_tablespaces_panel())
        
        # 6. 更新缓存命中率
        self.layout["cache"].update(self._get_cache_panel())
        
        # 7. 更新WAL状态
        self.layout["wal"].update(self._get_wal_panel())

    def _get_overview_panel(self) -> Panel:
        """获取数据库概览面板"""
        try:
            uptime = "未知"
            if self.uptime_start:
                now = datetime.datetime.now(self.uptime_start.tzinfo)
                uptime_delta = now - self.uptime_start
                days = uptime_delta.days
                hours, remainder = divmod(uptime_delta.seconds, 3600)
                minutes, seconds = divmod(remainder, 60)
                uptime = f"{days}天 {hours:02}:{minutes:02}:{seconds:02}"
            
            # 获取数据库大小
            db_size_query = "SELECT pg_size_pretty(pg_database_size(current_database()))"
            db_size = self._execute_query(db_size_query)[0][0] if self._execute_query(db_size_query) else "未知"
            
            # 获取活跃连接数
            active_conn_query = "SELECT count(*) FROM pg_stat_activity WHERE state = 'active'"
            active_connections = self._execute_query(active_conn_query)[0][0] if self._execute_query(active_conn_query) else 0
            
            # 获取数据库和表数量
            db_count_query = "SELECT count(*) FROM pg_database"
            db_count = self._execute_query(db_count_query)[0][0] if self._execute_query(db_count_query) else 0
            
            table_count_query = "SELECT count(*) FROM pg_stat_user_tables"
            table_count = self._execute_query(table_count_query)[0][0] if self._execute_query(table_count_query) else 0
            
            overview_table = Table(box=ROUNDED, expand=True, show_header=False)
            overview_table.add_column("属性", style="cyan")
            overview_table.add_column("值", style="green")
            
            overview_table.add_row("PostgreSQL版本", self.version_info.split(",")[0] if self.version_info else "未知")
            overview_table.add_row("启动时间", self.uptime_start.strftime("%Y-%m-%d %H:%M:%S") if self.uptime_start else "未知")
            overview_table.add_row("运行时间", uptime)
            overview_table.add_row("数据库大小", db_size)
            overview_table.add_row("活跃连接数", str(active_connections))
            overview_table.add_row("数据库数量", str(db_count))
            overview_table.add_row("表数量", str(table_count))
            
            return Panel(overview_table, title="数据库概览", border_style="bright_blue")
        except Exception as e:
            logger.error(f"获取数据库概览时出错: {e}")
            return Panel("获取数据库概览时出错", title="数据库概览", border_style="red")
    
    def _get_connections_panel(self) -> Panel:
        """获取连接信息面板"""
        try:
            # 获取连接统计
            connections_query = """
            SELECT 
                datname as database,
                count(*) as total,
                count(*) FILTER (WHERE state = 'active') as active,
                count(*) FILTER (WHERE state = 'idle') as idle,
                count(*) FILTER (WHERE state = 'idle in transaction') as idle_in_txn
            FROM pg_stat_activity
            WHERE datname IS NOT NULL
            GROUP BY datname
            ORDER BY total DESC
            LIMIT 10
            """
            connections = self._execute_query(connections_query)
            
            # 创建表格
            conn_table = Table(box=ROUNDED, expand=True)
            conn_table.add_column("数据库", style="cyan")
            conn_table.add_column("总连接数", style="green", justify="right")
            conn_table.add_column("活跃", style="yellow", justify="right")
            conn_table.add_column("空闲", style="blue", justify="right")
            conn_table.add_column("事务中空闲", style="red", justify="right")
            
            for conn in connections:
                conn_table.add_row(
                    str(conn[0]),
                    str(conn[1]),
                    str(conn[2]),
                    str(conn[3]),
                    str(conn[4])
                )
                
            # 计算连接数与最大连接数的比例
            max_conn_query = "SHOW max_connections"
            max_conn_result = self._execute_query(max_conn_query)
            max_connections = int(max_conn_result[0][0]) if max_conn_result else 100
            
            current_conn_query = "SELECT count(*) FROM pg_stat_activity"
            current_conn_result = self._execute_query(current_conn_query)
            current_connections = current_conn_result[0][0] if current_conn_result else 0
            
            # 添加进度条
            conn_ratio = min(current_connections / max_connections, 1.0)
            conn_ratio_text = f"连接使用率: {current_connections}/{max_connections} ({conn_ratio:.1%})"
            
            # 根据使用率设置颜色
            color = "green"
            if conn_ratio > 0.7:
                color = "yellow"
            if conn_ratio > 0.9:
                color = "red"
                
            progress_bar = ProgressBar(total=100, completed=int(conn_ratio * 100), style=color)
            
            # 创建包含表格和进度条的布局
            container = Layout()
            container.split(
                Layout(conn_table),
                Layout(Text(conn_ratio_text, style=color), size=1),
                Layout(progress_bar, size=1)
            )
            
            # 返回面板
            return Panel(container, title="连接情况", border_style="bright_blue")
            
        except Exception as e:
            logger.error(f"获取连接信息时出错: {e}")
            return Panel("获取连接信息时出错", title="连接情况", border_style="red")
    
    def _get_queries_panel(self) -> Panel:
        """获取查询性能面板"""
        try:
            # 检查pg_stat_statements扩展是否可用
            extension_query = """
            SELECT count(*) FROM pg_extension WHERE extname = 'pg_stat_statements'
            """
            extension_result = self._execute_query(extension_query)
            has_statements = extension_result[0][0] > 0 if extension_result else False
            
            if has_statements:
                # 获取TOP 10查询
                query = """
                SELECT 
                    substring(query, 1, 80) as query,
                    calls,
                    total_exec_time / 1000 as total_time_s,
                    (total_exec_time / calls) / 1000 as avg_time_s,
                    rows
                FROM pg_stat_statements
                ORDER BY total_exec_time DESC
                LIMIT 10
                """
                results = self._execute_query(query)
                
                # 创建表格
                table = Table(box=ROUNDED, expand=True)
                table.add_column("查询", style="cyan", max_width=80, overflow="fold")
                table.add_column("调用次数", style="green", justify="right")
                table.add_column("总时间(秒)", style="yellow", justify="right")
                table.add_column("平均时间(秒)", style="blue", justify="right")
                table.add_column("行数", style="magenta", justify="right")
                
                for row in results:
                    query_text = row[0].replace("\n", " ")
                    if len(query_text) > 80:
                        query_text = query_text[:77] + "..."
                    
                    table.add_row(
                        query_text,
                        f"{row[1]:,}",
                        f"{row[2]:.2f}",
                        f"{row[3]:.4f}",
                        f"{row[4]:,}"
                    )
                    
                return Panel(table, title="查询性能 TOP 10", border_style="bright_blue")
            else:
                # 显示正在运行的查询
                active_query = """
                SELECT 
                    datname as database,
                    usename as username,
                    state,
                    EXTRACT(EPOCH FROM (now() - query_start)) as duration_s,
                    substring(query, 1, 80) as query
                FROM pg_stat_activity
                WHERE state = 'active' AND pid <> pg_backend_pid()
                ORDER BY duration_s DESC
                LIMIT 10
                """
                results = self._execute_query(active_query)
                
                # 创建表格
                table = Table(box=ROUNDED, expand=True)
                table.add_column("数据库", style="cyan")
                table.add_column("用户", style="green")
                table.add_column("状态", style="yellow")
                table.add_column("持续时间(秒)", style="blue", justify="right")
                table.add_column("查询", style="magenta", max_width=80, overflow="fold")
                
                for row in results:
                    query_text = row[4].replace("\n", " ")
                    if len(query_text) > 80:
                        query_text = query_text[:77] + "..."
                        
                    # 根据查询时间设置颜色
                    duration_style = "green"
                    if row[3] > 30:
                        duration_style = "yellow"
                    if row[3] > 300:
                        duration_style = "red"
                        
                    table.add_row(
                        str(row[0]),
                        str(row[1]),
                        str(row[2]),
                        Text(f"{row[3]:.1f}", style=duration_style),
                        query_text
                    )
                
                message = "\n⚠️ 提示: 未启用pg_stat_statements扩展，只能显示当前活跃查询。\n启用扩展可获取完整查询性能统计。"
                
                # 创建包含表格和消息的布局
                container = Layout()
                container.split(
                    Layout(table),
                    Layout(Text(message, style="yellow"), size=3)
                )
                
                # 返回面板
                return Panel(container, title="正在运行的查询", border_style="bright_blue")
                
        except Exception as e:
            logger.error(f"获取查询性能时出错: {e}")
            return Panel(f"获取查询性能时出错: {str(e)}", title="查询性能", border_style="red")

    def _get_tablespaces_panel(self) -> Panel:
        """获取表空间使用情况面板"""
        try:
            # 获取表空间信息
            tablespaces_query = """
            SELECT 
                spcname AS tablespace,
                pg_size_pretty(pg_tablespace_size(spcname)) AS size
            FROM pg_tablespace
            ORDER BY pg_tablespace_size(spcname) DESC
            """
            tablespaces = self._execute_query(tablespaces_query)
            
            # 创建表格
            table = Table(box=ROUNDED, expand=True)
            table.add_column("表空间", style="cyan")
            table.add_column("大小", style="green", justify="right")
            
            for ts in tablespaces:
                table.add_row(str(ts[0]), str(ts[1]))
                
            return Panel(table, title="表空间使用情况", border_style="bright_blue")
        except Exception as e:
            logger.error(f"获取表空间信息时出错: {e}")
            return Panel("获取表空间信息时出错", title="表空间使用情况", border_style="red")
    
    def _get_cache_panel(self) -> Panel:
        """获取缓存命中率面板"""
        try:
            # 查询缓存命中情况
            cache_query = """
            SELECT 
                datname,
                blks_hit,
                blks_read,
                CASE WHEN (blks_hit + blks_read) > 0 
                    THEN round(100 * blks_hit / (blks_hit + blks_read), 2)
                    ELSE 0 
                END AS hit_ratio
            FROM pg_stat_database
            WHERE datname IS NOT NULL AND datname NOT IN ('template0', 'template1')
            ORDER BY hit_ratio DESC
            """
            cache_stats = self._execute_query(cache_query)
            
            # 创建表格
            table = Table(box=ROUNDED, expand=True)
            table.add_column("数据库", style="cyan")
            table.add_column("缓存命中", style="green", justify="right")
            table.add_column("磁盘读取", style="yellow", justify="right")
            table.add_column("命中率(%)", style="bright_blue", justify="right")
            table.add_column("状态", justify="center")
            
            # 全局命中率统计
            total_hit = 0
            total_read = 0
            
            for row in cache_stats:
                db_name = row[0]
                hits = row[1]
                reads = row[2]
                ratio = row[3]
                
                # 累计总数
                total_hit += hits
                total_read += reads
                
                # 根据命中率设置状态图标和颜色
                if ratio >= 95:
                    status = "🟢"
                    ratio_style = "green"
                elif ratio >= 80:
                    status = "🟡"
                    ratio_style = "yellow"
                else:
                    status = "🔴"
                    ratio_style = "red"
                    
                table.add_row(
                    str(db_name),
                    f"{hits:,}",
                    f"{reads:,}",
                    Text(f"{ratio:.2f}", style=ratio_style),
                    status
                )
                
            # 计算全局命中率
            global_ratio = 0
            if (total_hit + total_read) > 0:
                global_ratio = 100.0 * total_hit / (total_hit + total_read)
                
            # 根据全局命中率设置颜色
            color = "green"
            if global_ratio < 95:
                color = "yellow"
            if global_ratio < 80:
                color = "red"
                
            # 创建全局命中率进度条
            progress_bar = ProgressBar(total=100, completed=min(int(global_ratio), 100), style=color)
            global_text = f"全局缓存命中率: {global_ratio:.2f}%"
            
            # 创建包含表格和进度条的布局
            container = Layout()
            container.split(
                Layout(table),
                Layout(Text(global_text, style=color), size=1),
                Layout(progress_bar, size=1)
            )
            
            # 返回面板
            return Panel(container, title="缓存命中率", border_style="bright_blue")
            
        except Exception as e:
            logger.error(f"获取缓存命中率时出错: {e}")
            return Panel(f"获取缓存命中率时出错: {str(e)}", title="缓存命中率", border_style="red")
    
    def _get_wal_panel(self) -> Panel:
        """获取WAL状态面板"""
        try:
            # 创建WAL信息表格
            wal_table = Table(box=ROUNDED, expand=True, show_header=False)
            wal_table.add_column("属性", style="cyan")
            wal_table.add_column("值", style="green")
            
            # 根据是否为从库使用不同的查询
            if hasattr(self, 'is_replica') and self.is_replica:
                # 从库WAL查询
                wal_query = "SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn()"
                wal_result = self._execute_query(wal_query)
                
                if wal_result:
                    receive_lsn = wal_result[0][0]
                    replay_lsn = wal_result[0][1]
                    
                    wal_table.add_row("最后接收LSN", str(receive_lsn))
                    wal_table.add_row("最后回放LSN", str(replay_lsn))
                    
                    # 获取延迟信息
                    lag_query = """
                    SELECT 
                        CASE 
                            WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn() 
                            THEN 0 
                            ELSE EXTRACT(EPOCH FROM now() - pg_last_xact_replay_timestamp())::INTEGER 
                        END AS lag_seconds
                    """
                    lag_result = self._execute_query(lag_query)
                    
                    if lag_result:
                        lag_seconds = lag_result[0][0]
                        lag_text = f"{lag_seconds} 秒"
                        
                        # 使用不同颜色表示不同的延迟状态
                        lag_style = "green"
                        if lag_seconds > 60:
                            lag_style = "yellow"
                        if lag_seconds > 300:
                            lag_style = "red"
                            
                        wal_table.add_row("复制延迟", Text(lag_text, style=lag_style))
                
                # 查询恢复状态
                recovery_query = "SELECT pg_is_wal_replay_paused()"
                recovery_result = self._execute_query(recovery_query)
                
                if recovery_result:
                    is_paused = recovery_result[0][0]
                    status = "暂停" if is_paused else "活跃"
                    wal_table.add_row("回放状态", status)
            else:
                # 主库WAL查询
                try:
                    wal_query = "SELECT pg_current_wal_lsn(), pg_walfile_name(pg_current_wal_lsn())"
                    wal_result = self._execute_query(wal_query)
                    
                    if wal_result:
                        current_lsn = wal_result[0][0]
                        current_file = wal_result[0][1]
                        
                        wal_table.add_row("当前LSN", str(current_lsn))
                        wal_table.add_row("当前WAL文件", str(current_file))
                except Exception as e:
                    logger.warning(f"查询WAL LSN时出错: {e}")
                    # 尝试旧版PostgreSQL函数名
                    try:
                        wal_query_old = "SELECT pg_current_xlog_location(), pg_xlogfile_name(pg_current_xlog_location())"
                        wal_result_old = self._execute_query(wal_query_old)
                        
                        if wal_result_old:
                            current_lsn = wal_result_old[0][0]
                            current_file = wal_result_old[0][1]
                            
                            wal_table.add_row("当前LSN", str(current_lsn))
                            wal_table.add_row("当前WAL文件", str(current_file))
                    except Exception:
                        wal_table.add_row("WAL信息", "无法获取")
                
                # 获取归档状态
                try:
                    archive_query = """
                    SELECT 
                        count(*) as failed_count
                    FROM pg_stat_archiver
                    WHERE last_failed_time > last_archived_time
                    """
                    archive_result = self._execute_query(archive_query)
                    
                    if archive_result:
                        failed_count = archive_result[0][0]
                        
                        if failed_count > 0:
                            wal_table.add_row("WAL归档状态", Text("有失败", style="red"))
                        else:
                            wal_table.add_row("WAL归档状态", Text("正常", style="green"))
                except Exception as e:
                    logger.warning(f"查询归档状态时出错: {e}")
            
            # 获取检查点信息
            checkpoint_query = """
            SELECT 
                name,
                setting
            FROM pg_settings
            WHERE name IN ('checkpoint_timeout', 'checkpoint_completion_target', 'max_wal_size')
            """
            checkpoint_result = self._execute_query(checkpoint_query)
            
            # 添加检查点配置
            if checkpoint_result:
                # 提取结果，注意索引取决于查询顺序
                for row in checkpoint_result:
                    if row[0] == 'checkpoint_timeout':
                        wal_table.add_row("检查点超时", f"{row[1]}秒")
                    elif row[0] == 'checkpoint_completion_target':
                        wal_table.add_row("检查点完成目标", str(row[1]))
                    elif row[0] == 'max_wal_size':
                        wal_table.add_row("最大WAL大小", str(row[1]))
            
            # 获取WAL生成速率（仅适用于主库）
            if not hasattr(self, 'is_replica') or not self.is_replica:
                # 获取WAL生成速率相关代码不变
                wal_stats_query = """
                SELECT 
                    now() as current_time,
                    %s as current_lsn,
                    pg_wal_lsn_diff(%s, '0/0') as wal_bytes
                """
                
                # 根据PostgreSQL版本使用正确的函数
                if self.version_info and "PostgreSQL 9." in self.version_info:
                    # PostgreSQL 9.x 版本
                    wal_stats_query = wal_stats_query % (
                        "pg_current_xlog_location()",
                        "pg_current_xlog_location()"
                    )
                else:
                    # PostgreSQL 10+ 版本
                    wal_stats_query = wal_stats_query % (
                        "pg_current_wal_lsn()",
                        "pg_current_wal_lsn()"
                    )
                
                try:
                    # 保存第一次查询结果
                    first_stats = self._execute_query(wal_stats_query)
                    
                    # 等待一段时间后再次查询（减少时间，避免阻塞过长）
                    time.sleep(0.5)  # 缩短等待时间以减少阻塞
                    
                    # 再次查询以计算速率
                    second_stats = self._execute_query(wal_stats_query)
                    
                    # 计算WAL生成速率
                    if first_stats and second_stats:
                        first_bytes = first_stats[0][2]
                        second_bytes = second_stats[0][2]
                        time_diff = (second_stats[0][0] - first_stats[0][0]).total_seconds()
                        
                        if time_diff > 0:
                            # 处理decimal.Decimal类型
                            # 将Decimal转换为float以避免类型错误
                            first_bytes_float = float(first_bytes) if hasattr(first_bytes, 'to_eng_string') else first_bytes
                            second_bytes_float = float(second_bytes) if hasattr(second_bytes, 'to_eng_string') else second_bytes
                            
                            # 计算每秒生成的WAL字节数
                            bytes_per_sec = (second_bytes_float - first_bytes_float) / time_diff
                            
                            # 转换为适当的单位
                            if bytes_per_sec < 1024:
                                rate_str = f"{bytes_per_sec:.2f} B/s"
                            elif bytes_per_sec < 1024 * 1024:
                                rate_str = f"{bytes_per_sec / 1024:.2f} KB/s"
                            else:
                                rate_str = f"{bytes_per_sec / (1024 * 1024):.2f} MB/s"
                                
                            wal_table.add_row("WAL生成速率", rate_str)
                except Exception as e:
                    logger.warning(f"计算WAL生成速率时出错: {e}")
            
            return Panel(wal_table, title="WAL状态", border_style="bright_blue")
            
        except Exception as e:
            logger.error(f"获取WAL状态时出错: {e}")
            return Panel(f"获取WAL状态时出错: {str(e)}", title="WAL状态", border_style="red")

class PostgresqlMonitorManager:
    """PostgreSQL数据库监控管理类，用于集成到菜单系统"""
    
    def __init__(self):
        """初始化监控管理器"""
        self.monitor = PostgresqlMonitor()
        
    def start_monitoring(self):
        """启动实时监控仪表板"""
        print_info("正在启动PostgreSQL监控仪表板...")
        refresh_interval = get_input("请输入刷新间隔(秒)", "5")
        
        try:
            refresh_interval = int(refresh_interval)
            self.monitor.refresh_interval = max(1, refresh_interval)  # 确保最小间隔为1秒
        except ValueError:
            print_warning(f"无效的刷新间隔 '{refresh_interval}'，使用默认值 5 秒")
            self.monitor.refresh_interval = 5
            
        print_info(f"监控仪表板将每 {self.monitor.refresh_interval} 秒刷新一次")
        print_info("按 Ctrl+C 可随时退出监控")
        
        try:
            self.monitor.start()
        except KeyboardInterrupt:
            print_info("用户中断，退出监控")
        except Exception as e:
            print_error(f"启动监控时发生错误: {e}")
            logger.exception("监控启动异常")
            
    def check_connection_settings(self):
        """检查并配置数据库连接设置"""
        if self.monitor.conn and not self.monitor.conn.closed:
            print_success("已连接到数据库")
            return True
            
        print_info("配置数据库连接...")
        host = get_input("请输入数据库主机", "localhost")
        port = get_input("请输入数据库端口", "5432")
        dbname = get_input("请输入数据库名", "postgres")
        user = get_input("请输入用户名", "postgres")
        password = get_input("请输入密码(留空则无密码)")
        
        try:
            port = int(port)
        except ValueError:
            print_error(f"无效的端口号 '{port}'，使用默认值 5432")
            port = 5432
            
        print_info(f"正在连接到 {host}:{port}/{dbname} 数据库...")
        
        if self.monitor.connect(host, port, dbname, user, password or None):
            print_success("成功连接到数据库")
            return True
        else:
            print_error("连接数据库失败")
            return False

def main():
    """监控模块主函数"""
    monitor_manager = PostgresqlMonitorManager()
    if monitor_manager.check_connection_settings():
        monitor_manager.start_monitoring()

if __name__ == "__main__":
    main() 